// utils/notificationService.js
import Stomp from 'stompjs';
import {
	showAppPush
} from '@/components/APPPush/index.js';
import config from '@/config/index.js';

// --- 配置 ---
const WS_BASE_URL = config.websocketURL;
const MAX_RECONNECT_ATTEMPTS = 5;
const RECONNECT_DELAY = 5000;

// --- 状态变量 ---
let stompClient = null;
let currentUserId = null;
let currentUserToken = null;
let socketTask = null; // APP端：uni.connectSocket 返回的 SocketTask
let webSocket = null; // H5端：原生 WebSocket 实例
let reconnectAttempts = 0;
let isManualDisconnect = false; // 标记是否为手动断开

/**
 * 日志工具函数
 */
function log(message, type = 'info', data = null) {
	const prefix = `[通知服务] [${new Date().toLocaleTimeString()}]`;
	const logMethod = type === 'error' ? 'error' : type === 'warn' ? 'warn' : 'log';
	console[logMethod](`${prefix} ${message}`, data || '');
}

/**
 * 处理通知显示
 */
function handleNotificationDisplay(notificationData) {
	log('准备显示应用内推送通知', 'info', notificationData);

	if (!notificationData) {
		log('通知数据为空', 'warn');
		return;
	}

	const {
		notificationType = 'REPLY_COMMENT',
			title,
			senderNickname,
			contentPreview,
			content,
			senderId,
			senderAvatar = ''
	} = notificationData;

	// 确定模态框类型和内容
	let modalType = 'REPLY_COMMENT';
	let modalTitle = title || '新通知';
	let modalContent = contentPreview || content || '您有一条新消息，请查看。';
	let targetUserId = null;
	let targetNickName = null;

	if (notificationType === 'NEW_CHAT_MESSAGE') {
		modalType = 'OPEN_CHAT';
		modalTitle = senderNickname || '新消息';
		targetUserId = senderId;
		targetNickName = senderNickname || '对方';
	}

	const params = {
		inApp: true,
		voice: true,
		vibration: true,
		userId: targetUserId,
		nickName: targetNickName,
		messageType: modalType,
		messageTitle: modalTitle,
		messageContent: modalContent,
		messageImage: senderAvatar
	};

	showAppPush(params);
}

/**
 * 创建APP端的WebSocket适配器
 */
function createAppWebSocketAdapter() {
	return new Promise((resolve, reject) => {
		socketTask = uni.connectSocket({
			url: WS_BASE_URL,
			fail: (err) => reject(new Error(`uni.connectSocket 失败: ${err.errMsg}`))
		});

		const wsAdapter = {
			send: (data) => socketTask?.send({
				data
			}),
			close: () => socketTask?.close(),
		};

		socketTask.onOpen(() => {
			log('WebSocket连接已建立', 'success');
			wsAdapter.onopen?.();
		});

		socketTask.onMessage((res) => {
			wsAdapter.onmessage?.({
				data: res.data
			});
		});

		socketTask.onClose((res) => {
			log(`WebSocket连接关闭: ${res.code} - ${res.reason}`, 'info');
			wsAdapter.onclose?.(res);
			handleDisconnect(true);
		});

		socketTask.onError((err) => {
			log(`WebSocket连接错误: ${err.errMsg}`, 'error');
			wsAdapter.onerror?.(err);
			handleDisconnect(true);
		});

		resolve(wsAdapter);
	});
}

/**
 * 创建H5端的WebSocket适配器
 */
function createH5WebSocketAdapter() {
	return new Promise((resolve, reject) => {
		try {
			webSocket = new WebSocket(WS_BASE_URL);
			const wsAdapter = webSocket;

			wsAdapter.onopen = () => {
				log('WebSocket连接已建立', 'success');
			};

			wsAdapter.onclose = (event) => {
				log(`WebSocket连接关闭: ${event.code} - ${event.reason}`, 'info');
				handleDisconnect(true);
			};

			wsAdapter.onerror = (error) => {
				log('WebSocket连接错误', 'error', error);
				handleDisconnect(true);
			};

			resolve(wsAdapter);
		} catch (error) {
			reject(new Error(`创建 WebSocket 失败: ${error.message}`));
		}
	});
}

/**
 * 初始化STOMP客户端并建立连接
 */
function initializeStompClient(wsAdapter) {
	return new Promise((resolve, reject) => {
		stompClient = Stomp.over(wsAdapter);
		stompClient.debug = null; // 关闭STOMP的console.log输出

		const connectHeaders = {
			'Authorization': 'Bearer ' + currentUserToken
		};

		stompClient.connect(
			connectHeaders,
			// 连接成功回调
			(frame) => {
				log('STOMP 已连接', 'success');
				reconnectAttempts = 0;
				isManualDisconnect = false;
				setupSubscriptions();
				resolve('STOMP 已连接');
			},
			// 连接失败回调
			(error) => {
				const errMsg = `STOMP 连接失败: ${error.headers?.message || error}`;
				log(errMsg, 'error');
				handleDisconnect(true);
				reject(new Error(errMsg));
			}
		);
	});
}

/**
 * 设置消息订阅
 */
function setupSubscriptions() {
	if (!stompClient) return;

	const userQueue = `/user/queue/notifications`;

	stompClient.subscribe(userQueue, (message) => {
		try {
			const notificationData = JSON.parse(message.body);
			handleNotificationDisplay(notificationData);
		} catch (error) {
			log(`处理消息失败: ${error.message}`, 'error', {
				rawMessage: message.body
			});
		}
	});

	log(`已订阅消息队列: ${userQueue}`, 'info');
}

/**
 * 连接WebSocket
 */
function connectWebSocket() {
	return new Promise((resolve, reject) => {
		// 前置检查
		if (!currentUserId || !currentUserToken) {
			return reject(new Error('用户ID和令牌是连接所必需的'));
		}

		if (stompClient && stompClient.connected) {
			return resolve('STOMP 已连接');
		}

		// 清理旧连接
		handleDisconnect(false);

		log(`尝试以用户 ${currentUserId} 连接...`, 'info');

		// 根据平台创建WebSocket适配器
		let adapterPromise;

		// #ifdef APP-PLUS
		adapterPromise = createAppWebSocketAdapter();
		// #endif

		// #ifdef H5
		adapterPromise = createH5WebSocketAdapter();
		// #endif

		adapterPromise
			.then(wsAdapter => initializeStompClient(wsAdapter))
			.then(resolve)
			.catch(reject);
	});
}

/**
 * 处理断开连接
 */
function handleDisconnect(shouldReconnect = false) {
	// 清理STOMP客户端
	if (stompClient) {
		try {
			if (stompClient.connected) {
				stompClient.disconnect(() => log('STOMP 已断开'));
			}
		} catch (error) {
			log('断开STOMP连接时发生错误', 'error', error);
		}
		stompClient = null;
	}

	// 清理平台特定的WebSocket实例
	// #ifdef APP-PLUS
	if (socketTask) {
		try {
			socketTask.close();
		} catch (error) {
			log('关闭APP WebSocket时发生错误', 'error', error);
		}
		socketTask = null;
	}
	// #endif

	// #ifdef H5
	if (webSocket) {
		try {
			webSocket.close();
		} catch (error) {
			log('关闭H5 WebSocket时发生错误', 'error', error);
		}
		webSocket = null;
	}
	// #endif

	// 处理重连逻辑
	if (shouldReconnect && !isManualDisconnect && currentUserId && currentUserToken) {
		attemptReconnect();
	}
}

/**
 * 尝试重新连接
 */
function attemptReconnect() {
	if (reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
		reconnectAttempts++;
		const delay = RECONNECT_DELAY * Math.pow(1.5, reconnectAttempts - 1); // 指数退避
		log(`准备在 ${delay / 1000}秒后重连... (第 ${reconnectAttempts} 次)`, 'info');

		setTimeout(() => {
			if (!isManualDisconnect && currentUserId && currentUserToken) {
				connectWebSocket().catch(error =>
					log(`重连失败: ${error.message}`, 'error')
				);
			}
		}, delay);
	} else {
		log(`已达到最大重连次数 (${MAX_RECONNECT_ATTEMPTS})`, 'error');
	}
}

export default {
	/**
	 * 连接WebSocket服务
	 */
	connect(userId, token) {
		currentUserId = String(userId);
		currentUserToken = token;
		reconnectAttempts = 0;
		isManualDisconnect = false;
		return connectWebSocket();
	},

	/**
	 * 断开WebSocket连接
	 */
	disconnect() {
		log('请求主动断开连接', 'info');
		isManualDisconnect = true;
		reconnectAttempts = MAX_RECONNECT_ATTEMPTS;
		handleDisconnect(false);
	},

	/**
	 * 检查是否已连接
	 */
	isConnected() {
		return !!(stompClient && stompClient.connected);
	},

	/**
	 * 获取当前连接状态信息
	 */
	getStatus() {
		return {
			connected: this.isConnected(),
			userId: currentUserId,
			reconnectAttempts,
			isManualDisconnect
		};
	}
};